package org.third.integration.auth.jaas.advance.resource;

import java.security.Permission;
import java.security.PermissionCollection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ResourcePermissionCollection extends PermissionCollection {

    /**
     * 
     */
    private static final long serialVersionUID = 8706634602802976421L;
    private Map<String, Map<String, java.security.Permission>> permissions;

    public ResourcePermissionCollection() {
        permissions = new ConcurrentHashMap<String, Map<String, java.security.Permission>>();
    }

    /**
     * @see PermissionCollection#elements()
     */
    public Enumeration<Permission> elements() {
        // System.out.println("DefaultResourceActionPermissionCollection.elements()");
        // Enumeration<Permission> elements = Collections.emptyEnumeration();
        java.util.Vector<java.security.Permission> enum1 = new java.util.Vector<java.security.Permission>();
        for (java.util.Iterator<Map<String, java.security.Permission>> permission = permissions.values()
                .iterator(); permission.hasNext();) {
            enum1.addAll(permission.next().values());
        }
        return enum1.elements();
    }

    /**
     * @see PermissionCollection#implies(Permission)
     */
    public boolean implies(Permission permission) {
        // System.out.println("DefaultResourceActionPermissionCollection.implies()");

        if (!(permission instanceof ResourcePermission))
            throw new IllegalArgumentException("Wrong Permission type");

        ResourcePermission rcsPermission = (ResourcePermission) permission;
        Hashtable aggregate = (Hashtable) permissions.get(rcsPermission.getName());
        if (aggregate == null)
            return false;

        Enumeration enum2 = aggregate.elements();
        while (enum2.hasMoreElements()) {
            ResourcePermission p = (ResourcePermission) enum2.nextElement();
            if (p.implies(permission))
                return true;
        }

        return false;
    }

    /**
     * @see PermissionCollection#add(Permission)
     */
    public void add(Permission permission) {
        if (isReadOnly())
            throw new IllegalArgumentException("Read only collection");

        if (!(permission instanceof ResourcePermission))
            throw new IllegalArgumentException("Wrong Permission type");

        // Same permission names may have different relationships.
        // Therefore permissions are aggregated by relationship.
        ResourcePermission rcsPermission = (ResourcePermission) permission;
        String relationShip = rcsPermission.getRelationShip();
        if (relationShip == null)
            relationShip = "none";

        Map<String, java.security.Permission> aggregate = (Map<String, java.security.Permission>) permissions
                .get(rcsPermission.getName());
        if (aggregate != null) {
            ResourcePermission existing = (ResourcePermission) aggregate.get(relationShip);
            if (existing != null)
                rcsPermission = merge(rcsPermission, existing);
        } else {
            aggregate = new ConcurrentHashMap<String, java.security.Permission>();
        }

        aggregate.put(relationShip, rcsPermission);
        permissions.put(rcsPermission.getName(), aggregate);
    }

    /**
     * This is called when the same name is added twice to the collection. The
     * actions are combine and the name is only stored once in the collection.
     */
    private ResourcePermission merge(ResourcePermission a, ResourcePermission b) {
        String aActions = a.getActions();
        if (aActions.equals(""))
            return b;

        String bActions = b.getActions();
        if (bActions.equals(""))
            return a;

        return new ResourcePermission(a.getName(), aActions + ", " + bActions);
    }

}
